﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace AutoHistory.Core
{
    public static class HistoryManager
    {
        public static void AddFile(string sourceFile)
        {
            FileInfo fi = new FileInfo(sourceFile);

            string historyPath = GetHistoryPath(fi);
            string destinationFile = Path.Combine(historyPath, fi.Name + "." + DateTime.Now.ToBinary().ToString());

            fi.CopyTo(destinationFile, true);

            CleanupHistory(sourceFile);
        }

        public static void RecoverFile(string sourceFile, long timestamp)
        {
            FileInfo sfi = new FileInfo(sourceFile);

            string historyPath = GetHistoryPath(sfi);
            string historyFile = Path.Combine(historyPath, sfi.Name + "." + timestamp.ToString());

            FileInfo historyFi = new FileInfo(historyFile);
            historyFi.CopyTo(sfi.FullName, true);
        }

        public static void OpenFile(string sourceFile, long timestamp)
        {
            Process.Start(HistoryManager.GetFilename(sourceFile, timestamp));
        }

        public static string GetFilename(string sourceFile, long timestamp)
        {
            FileInfo sfi = new FileInfo(sourceFile);

            string historyPath = GetHistoryPath(sfi);
            string historyFile = Path.Combine(historyPath, sfi.Name + "." + timestamp.ToString());

            string tempFile = Path.GetTempPath();
            FileInfo historyFi = new FileInfo(historyFile);

            string tempFileName = sfi.Name.Replace(sfi.Extension, timestamp.ToString() + sfi.Extension);

            historyFi = historyFi.CopyTo(Path.Combine(tempFile, tempFileName), true);

            return historyFi.FullName;
        }

        public static void DeleteFiles(string sourceFile, long[] timestamps)
        {
            FileInfo sfi = new FileInfo(sourceFile);

            string historyPath = GetHistoryPath(sfi);

            foreach (long ts in timestamps)
            {
                string historyFile = Path.Combine(historyPath, sfi.Name + "." + ts.ToString());
                File.Delete(historyFile);
            }
        }

        public static List<HistoryFile> GetHistoryList(string sourceFile)
        {
            FileInfo sfi = new FileInfo(sourceFile);
            string historyPath = GetHistoryPath(sfi);

            List<HistoryFile> history = new List<HistoryFile>();

            foreach (string file in Directory.GetFiles(historyPath, sfi.Name + ".*", SearchOption.TopDirectoryOnly))
            {
                history.Add(new HistoryFile(sourceFile, file));
            }

            return history;
        }

        private static void CleanupHistory(string sourceFile)
        {
            int maxFiles = Settings.Instance.MaxHistoryFiles;
            if (maxFiles < 1)
                return;

            List<HistoryFile> files = GetHistoryList(sourceFile);

            if (files.Count <= maxFiles)
                return;

            var sortedFiles = from of in files
                              orderby of.Date descending
                              select of;

            int count = 0;
            foreach (var item in sortedFiles)
            {
                count++;

                if (count <= maxFiles)
                    continue;

                HistoryManager.DeleteFiles(sourceFile, new long[] { item.Timestamp });
            }
        }

        internal static string GetHistoryPath(FileInfo fileInfo)
        {
            string path = string.Empty;

            if (Settings.Instance.UseGlobalHistoryLocation)
            {
                path = Path.Combine(Settings.Instance.GlobalHistoryLocation, Path.Combine(fileInfo.Directory.Name, Path.GetFileNameWithoutExtension(fileInfo.FullName)));
            }
            else
            {
                string historyFolder = ".AutoHistory";
                path = Path.Combine(fileInfo.DirectoryName, historyFolder);
            }

            if (!Directory.Exists(path))
            {
                DirectoryInfo di = Directory.CreateDirectory(path);
                if (!Settings.Instance.UseGlobalHistoryLocation)
                    di.Attributes |= FileAttributes.Hidden | FileAttributes.System;
                di.Refresh();
            }

            return path;
        }
    }
}
